package com.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
 * 消费者 基于子类的动态代理
 */
public class client {
    public static void main(String[] args) {
        /**
         * 动态代理
         *  特点：随用随创建，随用随加载。与装饰者不同的是，装饰者必须写好一个类。
         *  作用：不修改源码，对方法加强
         *  分类： 基于接口
         *        基于子类
         *  基于子类：cglib第三方提供的Enhancer，
         *  1、如何创建代理对象。
         *      使用Enhancer类中create方法
         *     Enhancer.create()
         *  2、创建代理对象的要求
         *      被代理类不能是最终类
         *  3、create的参数
         *      class[] 指定字节码，指定被代理对象的字节码。
         *      InvocationHandler: new InvocationHandler()，只有一个invoke方法。用于增强的代码，用于如何代理，一般是该接口的实现类，谁用谁写，通常情况下匿名内部类，但不是必须。我们写的一般是该接口的子接口实现类：MethodInterceptor
         */
        final  Producer producer=new Producer();
        Producer productcglib=(Producer)Enhancer.create(producer.getClass(), new MethodInterceptor() {
            /**
             * 执行被代理对象任何方法都会经过该方法
             * @param o
             * @param method
             * @param objects
             * 以上三个和基于接口的动态代理invoke方法参数一样
             * @param methodProxy 当前执行方法的代理对象，用不上。
             * @return
             * @throws Throwable
             */
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
               Object returnvalue=null;
               //1获取方法执行的参数
                Float money=(Float)objects[0];
                //2判断当前方法
                if("afterService".equals(method.getName())){
                    //invoke第一个参数是被代理对象，第二个是需要增强的方法。
                    returnvalue=method.invoke(producer,money*0.8f);
                }else if ("saleProduct".equals(method.getName())){
                    returnvalue=method.invoke(producer,money*0.9f);
                }
                return returnvalue;
            }
        });
        //切记，在赋值的时候，需要把代理对象使用自己新建的对象来接收。
        productcglib.afterService(10000f);
        productcglib.saleProduct(10000f);
    }
}
